using MeasureAbstract.IMotionDevice;
using MeasureAbstract.ISignalGenerator;
using MeasureAbstract.IVectorNetworkAnalyzer;
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Threading;

namespace Ceyear1465F信号发生器
{
    public class SignalGenerator : ISignalGenerator
    {
        public override string Name => "信号发生器";

        public override string Vender => "Ceyear";

        public override string Model => "1465F";

        public override string Description => "思仪科技的信号发生器";

        public SignalGenerator()
        {
            Config = new SignalGeneratorConfig();
            Config.CommunicationList = new ObservableCollection<CommunicationMode>()
            {
                new CommunicationMode() {Name="TCP",Selected=true,Support=true },
                new CommunicationMode() {Name="GPIB",Selected=false,Support=true}
            };
            deviceInteractEnable = true;
            Config.DestIP = "192.168.1.101";
            Config.DestPort = "5025";
        }

        string LastSend = "";



        public override ObservableCollection<string> Unit => new ObservableCollection<string>() { "Hz", "KHz", "MHz", "GHz" };

        public override string SelectedTriggerInPort
        {
            get { return _SelectedTriggerInPort; }
            set
            {
                SetProperty(ref _SelectedTriggerInPort, value);
            }
        }

        private string _SelectedTriggerInPort = "触发输入";
        public override ObservableCollection<string> TriggerInPorts => new ObservableCollection<string>() { "触发输入" };

        public override string SelectedTriggerInSignal
        {
            get { return _SelectedTriggerInSignal; }
            set
            {
                SetProperty(ref _SelectedTriggerInSignal, value);
            }
        }
        public string _SelectedTriggerInSignal = "高电平";
        public override ObservableCollection<string> TriggerInSignals => new ObservableCollection<string>() { "高电平", "低电平" };

        public override string SelectedTriggerInAction
        {
            get { return _SelectedTriggerInAction; }
            set
            {
                SetProperty(ref _SelectedTriggerInAction, value);
            }
        }
        public string _SelectedTriggerInAction = "扫描一个点";

        public override ObservableCollection<string> TriggerInActions => new ObservableCollection<string>() { "扫描一个点" };

        public override string SelectedTriggerOutPort
        {
            get { return _SelectedTriggerOutPort; }
            set
            {
                SetProperty(ref _SelectedTriggerOutPort, value);
            }
        }
        public string _SelectedTriggerOutPort = "触发输出";

        public override ObservableCollection<string> TriggerOutPorts => new ObservableCollection<string>() { "触发输出" };

        public override string SelectedTriggerOutSignal
        {
            get { return _SelectedTriggerOutSignal; }
            set
            {
                SetProperty(ref _SelectedTriggerOutSignal, value);
            }
        }
        public string _SelectedTriggerOutSignal = "高电平";

        public override ObservableCollection<string> TriggerOutSignals => new ObservableCollection<string>() { "高电平", "低电平" };

        public override string SelectedTriggerOutTime
        {
            get { return _SelectedTriggerOutTime; }
            set
            {
                SetProperty(ref _SelectedTriggerOutTime, value);
            }
        }
        public string _SelectedTriggerOutTime = "扫描一个点后触发";

        public override ObservableCollection<string> TriggerOutTimes => new ObservableCollection<string>() { "扫描一个点后触发" };


        public string _SelectedTriggerInSignalWidth = "10";
        public override string SelectedTriggerInSignalWidth
        {
            get { return _SelectedTriggerInSignalWidth; }
            set
            {
                SetProperty(ref _SelectedTriggerInSignalWidth, value);
            }
        }
        public string _SelectedTriggerOutSignalWidth = "20000";
        public override string SelectedTriggerOutSignalWidth
        {
            get { return _SelectedTriggerOutSignalWidth; }
            set
            {
                SetProperty(ref _SelectedTriggerOutSignalWidth, value);
            }
        }

        int sens = 0;
        int vi = 0;
        int ret = 0;
        int CmdDelay_ms = 200;

        private void Write(string Data)
        {
            ret = Visa32.viPrintf(vi, Data);
            if (!Data.Contains("*OPC"))
            {
                LastSend = Data;

            }
            if (ret != Visa32.VI_SUCCESS)
            {
                throw new Exception($"向{Vender}_{Model}发送指令失败{ret}");
            }
        }

        private void Read(byte[] Data)
        {
            Visa32.viSetAttribute(vi, Visa32.VI_ATTR_TERMCHAR_EN, Visa32.VI_TRUE);
            ret = Visa32.viScanf(vi, "%t", Data);
            if (ret != Visa32.VI_SUCCESS)
            {
                throw new Exception($"从{Vender}_{Model}读取数据失败{ret}\n{LastSend}");
            }
        }

        public override void Connect()
        {
            if (ConnectState)
            {
                return;
            }
            string SelectedCommunication = "";
            foreach (var temp in Config.CommunicationList)
            {
                if (temp.Selected)
                {
                    SelectedCommunication = temp.Name;
                }
            }
            string ResourceName = "";
            int TimeOut_ms = 3000;
            switch (SelectedCommunication.ToUpper())
            {
                case "TCP":
                    ResourceName = $"TCPIP0::{Config.DestIP}::{Config.DestPort}::SOCKET"; break;
                case "GPIB":
                    ResourceName = $"GPIB0::{Config.GpibAddr}::INSTR"; break;
                case "USB":
                    ResourceName = $"USB0::0x1234::0x5678::0::INSTR"; break;
                default: throw new Exception($"不支持的通信方式{SelectedCommunication}");
            }
            Visa32.viOpenDefaultRM(out sens);
            int ret = Visa32.viOpen(sens, ResourceName, Visa32.VI_NO_LOCK, TimeOut_ms, out vi);
            if (ret != 0)
            {
                ConnectState = false;
                throw (new Exception($"{Vender}_{Model}打开失败{ret}"));
            }

            //发送一条信息，确定已经连接
            Write("*IDN?\n");
            byte[] D = new byte[1000];
            try
            {
                Read(D);
                if (!System.Text.Encoding.Default.GetString(D).Contains("CETC41,1465F,200700331,1.1.4"))
                {
                    throw new Exception($"{System.Text.Encoding.GetEncoding("GBK").GetString(D).Replace("\0", "").Replace("\n", "")}");
                }
            }
            catch (Exception e)
            {
                throw new Exception($"连接信号发生器失败!\n{e.Message}");
            }
            string Message = System.Text.Encoding.Default.GetString(D);
            ConnectState = true;
        }

        public override void DisConnect()
        {
            if (!ConnectState)
            {
                return;
            }
            //OutPut(false);
            //Wait(200);
            int ret = Visa32.viClose(vi);
            if (ret != Visa32.VI_SUCCESS)
            {
                throw new Exception($"{Name}_{Model}断开失败{ret}!");
            }
            ConnectState = false;
        }

        public override void ReSet()
        {
            MalfunctionState = false;
            //重置仪器
            Write("*RST\n");
            Wait(200);
            //清空状态
            Write("*CLS\n");
            Wait(200);
        }

        public override void OutPut(bool Open)
        {
            if (Open)
            {
                string cmd = $"OUTP ON\n";
                Write(cmd);
                Wait(200);
                //读取仪器状态确认
                Write("OUTPut?\n");
                byte[] Temp = new byte[128];
                try
                {
                    Read(Temp);
                    string Msg = System.Text.Encoding.Default.GetString(Temp).Replace("\0", "").Replace("\n", "").Replace("+", "");
                    if (Msg == "1")
                    {
                        RadioFrequencyState = true;
                    }
                    else
                    {
                        RadioFrequencyState = false;
                    }
                }
                catch (Exception)
                {
                    throw new Exception("无法确认仪器射频开关状态，请检查!");
                }

            }
            else
            {
                string cmd = $"OUTP OFF\n";
                Write(cmd);
                Wait(200);
                //读取仪器状态确认
                Write("OUTPut?\n");
                byte[] Temp = new byte[128];
                try
                {
                    Read(Temp);
                    string Msg = System.Text.Encoding.Default.GetString(Temp).Replace("\0", "").Replace("\n", "").Replace("+", "");
                    if (Msg == "1")
                    {
                        RadioFrequencyState = true;
                    }
                    else
                    {
                        RadioFrequencyState = false;
                    }
                }
                catch (Exception)
                {

                    throw new Exception("无法确认仪器射频开关状态，请检查!");
                }

            }
        }

        public override int SetEndFrequency(long EndFrequency, string Unit = "Hz")
        {
            string cmd = $"FREQuency:STOP {EndFrequency}\n";
            Write(cmd);
            return 0;
        }

        public override int SetIntermediateFrequencyBandwidth(long Bandwidth, string Unit = "Hz")
        {
            return 0;
        }

        public override int SetOutputPower(double OutputPower_dBm = -20)
        {
            string cmd = $"POWer {OutputPower_dBm}dBm\n";
            Write(cmd);
            return 0;
        }

        public override int SetScanPoints(int PointCount)
        {
            string cmd = $"SWEep:POINts {PointCount}\n";
            Write(cmd);
            return 0;
        }


        public override int SetStartFrequency(long StartFrequency, string Unit = "Hz")
        {
            String cmd = $"FREQuency:STAR {StartFrequency}\n";
            Write(cmd);
            return 0;
        }

        public override int SetSweepMode(SweepMode SweepMode = SweepMode.连续)
        {
            string cmd = $"";
            switch (SweepMode)
            {
                case SweepMode.连续:
                    cmd = $"INITiate:CONTinuous ON\n";
                    break;
                case SweepMode.保持:
                    cmd = $"INITiate:CONTinuous OFF\n";
                    break;
                default:
                    cmd = $"INITiate:CONTinuous ON\n";
                    break;
            }

            Write(cmd);
            return 0;
        }

        public override int SetSweepScope(SweepScope SweepScope = SweepScope.通道)
        {
            //默认一次一点，不需处理
            return 0;
        }

        public override int SetTriggerInput(string Interface, TriggerSignalType TriggerSignalType, double Width, double Delay_ms = 0)
        {
            //设为步进扫描模式
            string cmd = $"FREQuency:MODE SWE\n;*WAI\n";
            Write(cmd);
            Wait(100);
            //设置为连续扫
            SetSweepMode(SweepMode.连续);
            Wait(100);
            //设置回扫开关
            cmd = $"LIST:RETRace ON\n";
            Write(cmd);
            Wait(100);
            //设置为正向扫
            cmd = $"SWEep:DIRection UP\n";
            Write(cmd);
            Wait(100);



            //接口只有一个不用处理
            //信号类型

            //信号宽度

            //延时


            return 0;
        }

        public override int SetTriggerOut(bool Enable, string Interface, int ChannelNumber, string time, TriggerSignalType TriggerSignalType, double Width)
        {
            //设置单点的驻留时间，即脉冲宽度Width

            string cmd = $"SWEep:DWELl {Width/1000000}\n";
            Write(cmd);

            return 0;
        }

        public override int SetTriggerSource(TriggerSource TriggerSource)
        {
            string temp = "";
            switch (TriggerSource)
            {
                case TriggerSource.外部:
                    temp = "EXTernal";
                    break;
                case TriggerSource.总线:
                    temp = "BUS";
                    break;
                default:
                    temp = "EXTernal";
                    break;
            }

            string cmd = $"TRIG:SOUR IMM\n"; //起始触发源 自动
            cmd = $"SWEep:TRIGger:SOURce {temp}\n"; //扫描触发源，脉冲触发
            Write(cmd);
            return 0;
        }

        public override int GetError(ref string ErrorInfo)
        {
            string cmd = $"SYST:ERR?\n";
            Write(cmd);
            //读取仪器状态确认
            byte[] Temp = new byte[128];
            Read(Temp);
            ErrorInfo = System.Text.Encoding.GetEncoding("GBK").GetString(Temp).Replace("\0", "").Replace("\n", "");
            if (ErrorInfo.Contains("+0"))
            {
                return 0;
            }
            return 1;
        }

        public override int Wait(int PollingTime_ms)
        {
            //等待测量完成，两种方式
            //*OPC 测量完成后自动报告，未完成时，矢网不执行其他指令
            //*OPC? 查询是否完成，不会阻塞矢网，完成后读到1，否则0 ，可以用轮询的方式
            //这里采用轮询的方式，因为visa读取数据时，会有超时报错，不能等太长时间
            bool Completed = false;
            byte[] Data = new byte[8];
            while (!Completed)
            {
                Thread.Sleep(PollingTime_ms);//等待下一次轮询

                Write("*OPC?\n");
                Array.Clear(Data, 0, 8);
                Read(Data);
                if (System.Text.Encoding.Default.GetString(Data).Replace("\0", "") == "1\n")
                {
                    Completed = true;
                    break;
                }
            }
            return 0;
        }
    }
}
